#include "TileSystem.h"
#include "Map.h"
#include "..\\SGD Wrappers\\SGD_Geometry.h"
#include "..\TinyXML\tinyxml.h"
#include "GameObject.h"
#include <string>

TileSystem* TileSystem::instance = nullptr;

TileSystem* TileSystem::GetInstance()
{
	if (instance == nullptr)
	{
		instance = new TileSystem;
	}

	return instance;
}
void TileSystem::DeleteInstance()
{
	delete instance;
	instance = nullptr;
}
int TileSystem::Load(std::string path, std::string filename)
{
	std::string levelFile = path + filename;
	TiXmlDocument level(levelFile.c_str());

	if (level.LoadFile())
	{
		TiXmlHandle levelHandle(&level);
		TiXmlHandle rootHandle(0);
		TiXmlHandle layerHandle(0);
		TiXmlElement* element;
		
		element = levelHandle.FirstChildElement().Element();
		if (element)
		{
			rootHandle = TiXmlHandle(element);
			
			Map map;

			map.SetMapRows(static_cast<float>(atof(element->Attribute("rows"))));
			map.SetMapCols(static_cast<float>(atof(element->Attribute("cols"))));
			map.SetTileHeight(static_cast<float>(atof(element->Attribute("tile_height"))));
			map.SetTileWidth(static_cast<float>(atof(element->Attribute("tile_width"))));
			map.SetNumLayers(atoi(element->Attribute("num_layers")));

			element = element->FirstChildElement("Tileset");

			map.SetTilesetRows(static_cast<float>(atof(element->Attribute("rows"))));
			map.SetTilesetCols(static_cast<float>(atof(element->Attribute("cols"))));
						
			std::string image = element->GetText();
			std::string imagePath = path + image;
			map.LoadTileSet(imagePath.c_str());

			element = element->NextSiblingElement();

			//element = rootHandle.FirstChild("Layer").Element();
			
			for (; element; element = layerHandle.ToElement()->NextSiblingElement())
			{
				layerHandle = element;
				Layer layer;

				element = element->FirstChildElement("Tile");

				for (; element; element = element->NextSiblingElement())
				{
					if (strcmp(element->Value(), "Tile") == 0)
					{
						Tile tile;

						tile.tsPos.x = static_cast<float>(atof(element->Attribute("tileset_x")));
						tile.tsPos.y = static_cast<float>(atof(element->Attribute("tileset_y")));
						tile.mapPos.left = static_cast<float>(atof(element->Attribute("map_x"))) * map.GetTileWidth();
						tile.mapPos.top = static_cast<float>(atof(element->Attribute("map_y"))) * map.GetTileHeight();
						tile.mapPos.right = tile.mapPos.left + map.GetTileWidth();
						tile.mapPos.bottom = tile.mapPos.top + map.GetTileHeight();
						tile.event = element->Attribute("event");
						tile.isCollidable = strcmp(tile.event.c_str(), "TILECOLLISION") == 0 ? true : false;
						tile.type = element->Attribute("type");
						tile.activeRender = strcmp(element->Attribute("render"), "true") == 0 ? true : false;
						layer.tiles.push_back(tile);
					}
				}

				map.GetLayers().push_back(layer);
			}
			maps.push_back(map);
		}
		return maps.size() - 1;
	}
	else
	{
		return -1;
	}
}
void TileSystem::Unload()
{
	for (unsigned int m = 0; m < maps.size(); m++)
	{
		maps[m].UnloadTileSet();
	}
}
void TileSystem::Render(int mapID, SGD::Point camera, float screenWidth, float screenHeight)
{
	maps[mapID].Render(camera, screenWidth, screenHeight);
}
void TileSystem::CheckCollison(int mapID, GameObject* object)
{
	maps[mapID].CheckCollision(object);
}
bool TileSystem::CheckCollison(int mapID, SGD::Point position)
{
	return maps[mapID].CheckCollision(position);
}
void TileSystem::TurnOffTile(int mapID, SGD::Point point)
{
	maps[mapID].TurnOffTile(point);
}
void TileSystem::StartLevel(int mapID)
{
	maps[mapID].Start();
}
void TileSystem::SpawnEnemies(int mapID)
{
	maps[mapID].Spawn();
}
